package com.lagou.conf;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.fastjson.JSON;
import com.lagou.po.DbInfo;
import com.lagou.registry.ZkClientHolder;
import com.lagou.registry.ZkNodeUtil;
import com.lagou.service.BlogServiceImpl;
import com.lagou.spring.SpringBeanUtil;
import org.apache.curator.framework.recipes.cache.PathChildrenCache;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Service;

import javax.sql.DataSource;
import javax.swing.*;
import java.lang.reflect.Field;
import java.util.Map;

@Configuration
public class DbConf {

    @Bean
    public DataSource druidDataSource(){
        String nodeData = ZkNodeUtil.getNodeData("/config/db");
        DbInfo dbInfo = JSON.parseObject(nodeData,DbInfo.class);
        DruidDataSource dataSource = createDataSource(dbInfo);
        //开启线程监听
        Thread t =  new Thread(new Listener());
        t.setDaemon(true);
        t.start();
        return dataSource;
    }

    private static DruidDataSource createDataSource(DbInfo dbInfo) {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(dbInfo.getDbClassName());
        dataSource.setUsername(dbInfo.getUsername());
        dataSource.setPassword(dbInfo.getPassword());
        dataSource.setUrl(dbInfo.getConnString());
        return  dataSource;
    }

    static class Listener implements Runnable{


        @Override
        public void run() {
            try {
                //创建PathChildrenCache
                //参数：true代表缓存数据到本地
                PathChildrenCache pathChildrenCache = new PathChildrenCache(ZkClientHolder.client,"/config",true);
                //BUILD_INITIAL_CACHE 代表使用同步的方式进行缓存初始化。
                pathChildrenCache.start(PathChildrenCache.StartMode.BUILD_INITIAL_CACHE);
                pathChildrenCache.getListenable().addListener((cf, event) -> {
                    PathChildrenCacheEvent.Type eventType = event.getType();
                    String data = new String(event.getData().getData());
                    switch (eventType) {
                        case CHILD_UPDATED:
                            System.out.println("Child updated");
                            System.out.println(data);
                            //监听到了，怎么处理呢？
                            DataSource druidDataSource = (DataSource)SpringBeanUtil.ac.getBean("druidDataSource");
                            DbInfo dbInfo = JSON.parseObject(data,DbInfo.class);
                            druidDataSource = createDataSource(dbInfo);
                            Map<String, Object> beanMap = SpringBeanUtil.ac.getBeansWithAnnotation(Service.class);
                            for (Map.Entry<String, Object> entry : beanMap.entrySet()) {
                                Object bean = entry.getValue();
                                Field field = null;
                                try {
                                    field = bean.getClass().getDeclaredField("druidDataSource");
                                } catch (NoSuchFieldException e) {
                                    continue;
                                }
                                field.setAccessible(true);
                                field.set(bean,druidDataSource);
                            }
//                            BlogServiceImpl service = (BlogServiceImpl) SpringBeanUtil.ac.getBean("blogServiceImpl");
//                            service.setDruidDataSource(druidDataSource);
                            System.out.println("数据源替换完成");
                            break;
                        default:
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
